package com.foreveross.crawl.workers;

import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.UnableToInterruptJobException;
import org.quartz.impl.JobDetailImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.GlobalMapOperatorBeta1;
import com.foreveross.crawl.CrawlContext;
import com.foreveross.crawl.common.cfg.PropertyUtils;
import com.foreveross.crawl.common.cfg.system.EnginePropertiesLoader;
import com.foreveross.crawl.common.cfg.system.SystemPropertiesLoader;
import com.foreveross.crawl.common.em.TaskState;
import com.foreveross.crawl.common.exception.BusinessException;
import com.foreveross.crawl.dto.TaskModelDto;
import com.foreveross.crawl.vo.ProxyChannelRelateVO;
import com.foreveross.crawl.vo.TaskModelBeta1;
import com.foreveross.crawl.vo.TaskStatisticsBeta1;
import com.foreveross.ehcache.CacheUtil;
import com.foreveross.ehcache.TaskCacheVO;
import com.foreveross.taskservice.common.bean.TaskModel;
import com.foreveross.taskservice.common.model.AbstractChannelModel;
import com.foreveross.taskservice.common.model.airfreight.AirFreightChannelModel;
import com.foreveross.util.PropertesCustom;

/**
 * 定时获取获取任务
 * 
 * @author luofangyi
 * 
 */
public class CrawlBaseTaskWorkerBeta2 extends AbstractTaskWorker {

	private static Logger logger = LoggerFactory.getLogger(CrawlBaseTaskWorkerBeta2.class);
	public static boolean isDeal = true;
	
	@SuppressWarnings("deprecation")
	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		Object[] abstractTasks;
		JobDetailImpl baseJob;
		TaskModel model;
		String jobGroupName;
		logger.info("常规任务启动");
		long channelId = context.getJobDetail().getJobDataMap().getLong(CrawlContext.CRAWL_CHANNEL_ID);

		try {
//			dealTaskModel(channelId);
			jobGroupName = CrawlContext.CRAWL_TASK_CHANNEL_BASE + channelId;
			int max = PropertyUtils.getIntProperty(
					EnginePropertiesLoader.ENGINE_CHANNEL_TASK_MAXCOMPLICATING
							+ ".channel" + channelId,
					EnginePropertiesLoader.FILE_NAME, 5);
			int has = GlobalMapOperatorBeta1.getTaskSizeByChannel(channelId);;
//			int has = this.iTaskModelEntityApplication
//					.countTaskModelByChannelIdAndState(channelId, "DOING");
			if (has >= max) {
				logger.info(String.format("渠道[%s] 达到最大并发，常规任务等待下次执行！",
						channelId));
				return;
			}
			// 是否在本地构建任务信息
			boolean isLocalBuild = PropertyUtils.getBooleanProperty(
					PropertesCustom.SYSTEM_TASK_LOCAL_BUILD,
					SystemPropertiesLoader.FILE_NAME);
			if (isLocalBuild) {
				abstractTasks = this.getAbstractTask(channelId);
			} else {
				abstractTasks = super.iCrawlNodeBaseTaskApplication
						.getTaskQueueRecordEntitys(null, channelId, max - has);
			}
			if (abstractTasks == null || abstractTasks.length == 0) {
				return;
			}
			// logger.error("###########渠道ID：" + channelId + ",从MQ获取到的任务数:" +
			// ((abstractTasks == null || abstractTasks.length == 0) ? 0 :
			// abstractTasks.length));
			this.addTasksToMap(abstractTasks);
			for (Object ab : abstractTasks) {
				if (ab != null && ab instanceof TaskModel) {
					Scheduler scheduler = context.getScheduler();// new
																	// StdSchedulerFactory().getScheduler();
					model = (TaskModel) ab;
//					addChannelInfoToH2(model, channelId);
					baseJob = new JobDetailImpl();
					baseJob.setGroup(CrawlContext.CRAWL_TASK_CHANNEL_BASE
							+ channelId);
					baseJob.setName(model.getId());
					baseJob.setJobClass(DefaultQueueWorkerBeta2.class);
					baseJob.getJobDataMap().put(CrawlContext.CRAWL_TASK, model);
					baseJob.getJobDataMap().put(CrawlContext.CRAWL_CHANNEL_ID,
							channelId);
					// KeyMatcher<JobKey> matcher =
					// KeyMatcher.keyEquals(baseJob.getKey());
					// scheduler.getListenerManager().addJobListener(new
					// DefaultCrawlWorkerListenerBeta1(), matcher);
					Trigger trigger = TriggerBuilder
							.newTrigger()
							.withIdentity(
									"ImmediatelyOnceTriggerGroup"
											+ UUID.randomUUID().toString()
													.replaceAll("-", ""),
									"ImmediatelyOnceTriggerGroup").startNow()
							.build();
					this.jobToBeExecuted(model);
					// 立即触发
					scheduler.scheduleJob(baseJob, trigger);
					Thread.sleep(2000);
				}
			}

		} catch (Exception e) {
			logger.error("获取任务异常，渠道id为{}", channelId, e);
		} finally {
			baseJob = null;
			abstractTasks = null;
		}
	}

	private void dealTaskModel(Long channelId) throws BusinessException {
		if(isDeal){
			synchronized (CrawlBaseTaskWorkerBeta2.class) {
				this.iTaskModelEntityApplication.deleteValidTaskModel();
				isDeal = false;
			}
		}
	}

	@Override
	public void interrupt() throws UnableToInterruptJobException {
		// TODO Auto-generated method stub

	}

	/**
	 * 将任务加入到ehcache缓存中
	 * 
	 * @param tasks
	 */
	private void addTasksToEhcache(Object[] tasks) {
		for (Object ab : tasks) {
			if (ab == null) {
				continue;
			}
			if (ab instanceof TaskModel) {
				TaskModel model = (TaskModel) ab;
				TaskCacheVO vo = new TaskCacheVO(
						TaskModelBeta1.adapterTaskModel(model),
						TaskState.NORUN.getType());
				CacheUtil.putStringValueToCache(model.getId(), vo);
			}
			// TODO 当新版任务中心开发好后可继续添加
			// else if (ab instanceof Object){
			//
			// }
		}
	}

	private void addTasksToMap(Object[] tasks) {

		for (Object ab : tasks) {
			if (ab == null) {
				continue;
			}
			if (ab instanceof TaskModel) {
				TaskModel model = (TaskModel) ab;
				Long channelId = model.getChannel().getId();
				TaskModelBeta1 beta = TaskModelBeta1.adapterTaskModel(model);
				TaskModelDto dto = new TaskModelDto(model.getId(), channelId,
						beta.getChannelName(), beta.getIsProxyIp(),
						beta.getParamsJson(), beta.getMetadata(),
						beta.getTaskStartDate(), beta.getTaskEndDate(), 0l,
						model.getId(), CrawlContext.CRAWL_TASK_CHANNEL_BASE
								+ channelId, TaskState.DOING/*.NORUN*/.getType(), 
						beta.getEncoded(), beta.getTaskPublish(), 
						model.getProxyIp(), 0, new ArrayList<String>());
//				this.iTaskModelEntityApplication.addTaskModel(dto);
				try {
					GlobalMapOperatorBeta1.addTaskByChannel(channelId, dto);
//					GlobalMapOperatorBeta1.addTaskDoingNumber(channelId);
//					GlobalMapOperatorBeta1.addTaskNumber(channelId);
				} catch (Exception e) {
					logger.error(e.getLocalizedMessage());
				}
			}
			// TODO 当新版任务中心开发好后可继续添加
			// else if (ab instanceof Object){
			//
			// }
			
			
		}
	}

	private Object[] getAbstractTask(Long channelId) {

		// List<AbstractTask> taskList = new ArrayList<AbstractTask>();
		TaskModel task = new TaskModel();
		task.setAttachHbaseKey("20017");
		task.setCreateTime(new Date());
		task.setFromCity("PEK");
		task.setFromCityName("北京");
		task.setToCity("LAX");// 曼谷
		// task.setToCity("cnx");// 清迈
		// task.setToCity("pus");//釜山
		// task.setToCity("aal");//Aalborg 奥尔堡
		// task.setToCity("ath");//雅典
		task.setToCityName("洛杉矶");
		task.setFlightDate("2014-08-01");
		task.setReturnGrabDate("2014-08-31");
		task.setIsReturn(1);// 0:单程 1:往返
		task.setIsInternational(1);// 1 ： 国际
		task.setId(UUID.randomUUID().toString());
		AbstractChannelModel channel = new AirFreightChannelModel();
		channel.setId(channelId);
		channel.setName("东航");
		task.setChannel(channel);

		// taskList.add(task);
		Object[] tasks = new Object[1];
		tasks[0] = task;

		/*task = new TaskModel();
		task.setAttachHbaseKey("20017");
		task.setCreateTime(new Date());
		task.setFromCity("pek");
		task.setFromCityName("北京");
		// task.setToCity("bkk");//曼谷
		task.setToCity("cnx");// 清迈
		// task.setToCity("pus");//釜山
		// task.setToCity("aal");//Aalborg 奥尔堡
		// task.setToCity("ath");//雅典
		task.setToCityName("清迈");
		task.setFlightDate("2014-07-19");
		task.setReturnGrabDate("2014-07-28");
		task.setIsReturn(0);// 0:单程 1:往返
		task.setIsInternational(0);// 国际
		task.setId(UUID.randomUUID().toString());
		channel = new AirFreightChannelModel();
		channel.setId(channelId);
		channel.setName("泰航");
		task.setChannel(channel);
		tasks[1] = task;*/

		return tasks;
	}

	private synchronized void jobToBeExecuted(TaskModel task){
		try {
			this.updateTaskState(task.getChannel().getId(), task.getId(), TaskState.DOING.getType());
//			this.iTaskModelEntityApplication.updateTaskStartDate(task.getId(), DateUtil.formatDay(new Date(), "HH时mm分ss秒"));
			GlobalMapOperatorBeta1.updateTaskStartDate(task.getChannel().getId(), task.getId());
			GlobalMapOperatorBeta1.updateTaskDoingNumber(task.getChannel().getId());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		logger.info(String.format("开始执行抓取：[%s, %s], 从[%s(%s)]至[%s(%s)], 日期[%s]",
				task.getGrabChannel(), task.getId(), task.getFromCityName(),task.getFromCity(),task.getToCityName(),task.getToCity(), task.getFlightDate()));
	}
	
	private synchronized void updateTaskState(Long channel, String taskId, String state){
		try {
			GlobalMapOperatorBeta1.updateTaskState(channel, taskId, state);
//			this.iTaskModelEntityApplication.updateTaskState(taskId, state);
		} catch (Exception e) {
			logger.error(e.toString());
		}
	}
	

	private void addChannelInfoToH2(TaskModel model, long channelId) {
		try {
			ProxyChannelRelateVO vo = new ProxyChannelRelateVO(channelId, model.getChannel().getName(), new Date(), true);
			this.iProxyChannelRelateApplication.saveChannelInfo(vo);
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
	}
	
}
